import { ConstantEnum } from '@libs/common/enums';
import {
  BaseRepository,
  indexPaginateBuilder,
  showBuilderEntity,
} from '@libs/common/repository';
import { Inject, Injectable } from '@nestjs/common';
import { plainToInstance } from 'class-transformer';
import { DataSource, Equal, In } from 'typeorm';

import { OrderResult } from '@/constant.enum';

import {
  CreateDeviceExchangeLogDto,
  DeleteDeviceExchangeLogDto,
  DeviceExchangeEventOption,
  IndexDeviceExchangeLogDto,
  ShowDeviceExchangeLogDto,
  UpdateDeviceExchangeLogDto,
} from './dto/device-exchange-log.dto';
import { DeviceExchangeLog } from './entities/device-exchange-log.entity';

@Injectable()
export class DeviceExchangeLogService extends BaseRepository {
  constructor(
    @Inject(ConstantEnum.DB_DATA_SOURCE_MANAGER) dataSource: DataSource,
  ) {
    super(dataSource);
  }

  protected repository = this.getRepository(DeviceExchangeLog);

  protected repositoryManager = () => this.getRepository(DeviceExchangeLog);

  async index(dto: IndexDeviceExchangeLogDto) {
    const res = await indexPaginateBuilder({
      dto,
      repository: this.repository,
    });
    return res;
  }

  show<D extends ShowDeviceExchangeLogDto = ShowDeviceExchangeLogDto>(dto: D) {
    return showBuilderEntity(this.repository, dto);
  }

  async delete(dto: DeleteDeviceExchangeLogDto) {
    const { id, ids } = dto;
    if (id) {
      await this.repositoryManager().delete({ id: Equal(id) });
    } else if (ids) {
      await this.repositoryManager().delete({ id: In(ids) });
    }
    return;
  }

  update(dto: UpdateDeviceExchangeLogDto | UpdateDeviceExchangeLogDto[]) {
    const dtos = Array.isArray(dto) ? dto : [dto];
    const entities = plainToInstance(DeviceExchangeLog, dtos);

    return this.repositoryManager().save(entities);
  }

  async create(dto: CreateDeviceExchangeLogDto) {
    const entity = this.repositoryManager().create(
      plainToInstance(DeviceExchangeLog, dto),
    );

    await this.repositoryManager().insert(entity);

    return entity;
  }

  async errorCreate(dto: CreateDeviceExchangeLogDto) {
    const entity = this.repository.create(
      plainToInstance(DeviceExchangeLog, dto),
    );

    await this.repository.insert(entity);

    return entity;
  }

  async updateStatusByOrderNo(dto: {
    orderNo: string;
    status: DeviceExchangeLog['orderStatus'];
  }) {
    const entity = await this.repository.findOneBy({ orderNo: dto.orderNo });
    if (!entity) return;

    await this.repository.update(entity.id, {
      orderStatus: dto.status,
      deviceResult: dto.status,
    });
  }

  async deviceExchange(dto: DeviceExchangeEventOption) {
    if (dto.orderStatus === OrderResult['成功']) {
      return this.create(dto);
    } else {
      return this.errorCreate(dto);
    }
  }
}
